package cn.iocoder.yudao.module.pi.controller.admin.pipline.exec;

import cn.iocoder.yudao.framework.common.pojo.CommonResult;
import cn.iocoder.yudao.framework.common.pojo.PageResult;
import cn.iocoder.yudao.framework.common.util.object.BeanUtils;
import cn.iocoder.yudao.framework.tenant.core.aop.TenantIgnore;
import cn.iocoder.yudao.module.pi.controller.admin.pipline.deploy.vo.DeployBaseVO;
import cn.iocoder.yudao.module.pi.controller.admin.pipline.deploy.vo.DeployCreateReqVO;
import cn.iocoder.yudao.module.pi.controller.admin.pipline.exec.vo.*;
import cn.iocoder.yudao.module.pi.dal.dataobject.deploy.DeployDO;
import cn.iocoder.yudao.module.pi.dal.dataobject.exec.ExecDO;
import cn.iocoder.yudao.module.pi.dal.dataobject.task.TaskDO;
import cn.iocoder.yudao.module.pi.framework.config.HuaWeiIAMPoperties;
import cn.iocoder.yudao.module.pi.service.deploy.DeployService;
import cn.iocoder.yudao.module.pi.service.exec.ExecService;
import cn.iocoder.yudao.module.pi.service.task.TaskService;
import com.alibaba.fastjson2.JSON;
import com.huaweicloud.sdk.codeartspipeline.v2.CodeArtsPipelineClient;
import com.huaweicloud.sdk.codeartspipeline.v2.model.*;
import com.huaweicloud.sdk.codeartspipeline.v2.region.CodeArtsPipelineRegion;
import com.huaweicloud.sdk.core.auth.BasicCredentials;
import com.huaweicloud.sdk.core.auth.ICredential;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.Parameter;
import io.swagger.v3.oas.annotations.tags.Tag;
import lombok.extern.slf4j.Slf4j;
import org.springframework.web.bind.annotation.*;

import javax.annotation.Resource;
import javax.annotation.security.PermitAll;
import javax.validation.Valid;
import java.util.*;

import static cn.iocoder.yudao.framework.common.pojo.CommonResult.error;
import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success;

@Tag(name = "管理后台 - 流水线部署执行")
@RestController
@RequestMapping("/pi/pipline/exec")
@Slf4j
public class PiplineExecController {
    @Resource
    private HuaWeiIAMPoperties huaWeiIAMPoperties;

    @Resource
    private ExecService execService;
    @Resource
    private DeployService deployService;
    @Resource
    private TaskService taskService;

    @PostMapping("/create")
    @Operation(summary = "创建部署执行")
    //@PreAuthorize("@ss.hasPermission('pi:exec:create')")
    @PermitAll
    @TenantIgnore
    public CommonResult<ExecCreateRespVO> createExec(@Valid @RequestBody ExecCreateReqVO createReqVO) {
        ExecCreateRespVO execCreateRespVO = new ExecCreateRespVO();
        execCreateRespVO.setRunIds(new ArrayList<String>());
        DeployDO deploy = deployService.getDeploy(createReqVO.getDeployId());
        //获得tag列表
        List<DeployBaseVO.DataDTO> tagList = JSON.parseArray(deploy.getData(), DeployBaseVO.DataDTO.class);
        String batchId = UUID.randomUUID().toString();
        //每个tag都要发包
        tagList.forEach(tag-> {
            //每个env都需要发包
            createReqVO.getEnvs().forEach(env -> {
                exec(batchId,deploy,tag,env,execCreateRespVO);
            });
        });
        return success(execCreateRespVO);
    }

    private void exec(String batchId,DeployDO deploy,DeployBaseVO.DataDTO tag,String env,ExecCreateRespVO execCreateRespVO){
        //获得流水线任务列表
        List<TaskDO> taskList = taskService.getTaskList(env);
        TaskDO taskDO = taskList.get(0);
        Map<String,TaskDO> taskMap=new HashMap<>();
        taskList.forEach(task -> {
            taskMap.put(task.getTaskCiName(),task);
        });
        // The AK and SK used for authentication are hard-coded or stored in plaintext, which has great security risks. It is recommended that the AK and SK be stored in ciphertext in configuration files or environment variables and decrypted during use to ensure security.
        // In this example, AK and SK are stored in environment variables for authentication. Before running this example, set environment variables CLOUD_SDK_AK and CLOUD_SDK_SK in the local environment
        String ak = huaWeiIAMPoperties.getAk();
        String sk = huaWeiIAMPoperties.getSk();
        ICredential auth = new BasicCredentials()
                .withAk(ak)
                .withSk(sk);
        //设置region
        CodeArtsPipelineClient client = CodeArtsPipelineClient.newBuilder()
                .withCredential(auth)
                .withRegion(CodeArtsPipelineRegion.valueOf(taskDO.getRegion()))
                .build();
        RunPipelineRequest request = new RunPipelineRequest();
        //设置项目id
        request.withProjectId(taskDO.getProjectId());
        //设置流水线id
        request.withPipelineId(taskDO.getPiplineId());
        //设置sources
        List<RunPipelineDTOSources> listbodySources = new ArrayList<>();
        //设置variables
        List<RunPipelineDTOVariables> listbodyVariables = new ArrayList<>();
        listbodyVariables.add(new RunPipelineDTOVariables()
                .withName("releaseversion")
                .withValue(tag.getTag())
        );
        List<DeployCreateReqVO.DataDTO.ServicesDTO> services=tag.getServices();
        List<String> chooseStages = new ArrayList<>();
        List<String> chooseJobs = new ArrayList<>();
        services.forEach(service->{
            String serviceName = service.getName();
            TaskDO task= taskMap.get(serviceName);
            if(!chooseStages.contains(task.getStageCiId())){
                chooseStages.add(task.getStageCiId());
            }
            if(!chooseJobs.contains(task.getTaskCiId())){
                chooseJobs.add(task.getTaskCiId());
            }
        });
        //设置调用参数
        RunPipelineDTO body = new RunPipelineDTO();
        body.withSources(listbodySources);
        body.withVariables(listbodyVariables);
        body.setDescription(deploy.getInfo());
        body.setChooseJobs(chooseJobs);
        body.setChooseStages(chooseStages);
        request.withBody(body);
        try {
            //调用流水线
            RunPipelineResponse response = client.runPipeline(request);
            log.info("{}",response);
            execCreateRespVO.getRunIds().add(response.getPipelineRunId());
            ExecSaveReqVO createReqVO=new ExecSaveReqVO();
            createReqVO.setEnv(env);
            createReqVO.setDeployId(deploy.getId());
            createReqVO.setPiplineRunId(response.getPipelineRunId());
            createReqVO.setPiplineId(taskDO.getPiplineId());
            createReqVO.setProjectId(taskDO.getProjectId());
            createReqVO.setRegion(taskDO.getRegion());
            createReqVO.setTag(tag.getTag());
            createReqVO.setBatchId(batchId);
            execService.createExec(createReqVO);
        } catch (Exception e) {
            log.error(e.getMessage());
        }
    }

    @GetMapping("/getExecBatchTag")
    @Operation(summary = "获得同一批次部署的tag")
    @Parameter(name = "id", description = "编号", required = true, example = "1024")
    //@PreAuthorize("@ss.hasPermission('pi:exec:query')")
    @PermitAll
    @TenantIgnore
    public CommonResult<List<ExecDO>> getExecBatchTag(@RequestParam("id") Long id) {
        ExecDO exec = execService.getExec(id);
        //获得同一批次的tag
        List<ExecDO> batchExecs = execService.getExecBatchTag(exec);
        return CommonResult.success(batchExecs);
    }

    @PostMapping("/getExecWithRunDetail")
    @Operation(summary = "获得部署执行")
    @Parameter(name = "id", description = "编号", required = true, example = "1024")
    //@PreAuthorize("@ss.hasPermission('pi:exec:query')")
    @PermitAll
    @TenantIgnore
    public CommonResult<ExecWithRunDetailRespVO> getExecWithRunDetail(@RequestParam("id") Long id) {
        ExecDO exec = execService.getExec(id);
        ExecWithRunDetailRespVO execWithRunDetailRespVO = new ExecWithRunDetailRespVO();
        BeanUtils.copyProperties(exec, execWithRunDetailRespVO);
        // The AK and SK used for authentication are hard-coded or stored in plaintext, which has great security risks. It is recommended that the AK and SK be stored in ciphertext in configuration files or environment variables and decrypted during use to ensure security.
        // In this example, AK and SK are stored in environment variables for authentication. Before running this example, set environment variables CLOUD_SDK_AK and CLOUD_SDK_SK in the local environment
        String ak = huaWeiIAMPoperties.getAk();
        String sk = huaWeiIAMPoperties.getSk();
        ICredential auth = new BasicCredentials()
                .withAk(ak)
                .withSk(sk);
        CodeArtsPipelineClient client = CodeArtsPipelineClient.newBuilder()
                .withCredential(auth)
                .withRegion(CodeArtsPipelineRegion.valueOf(exec.getRegion()))
                .build();
        ShowPipelineRunDetailRequest request = new ShowPipelineRunDetailRequest();
        request.withProjectId(exec.getProjectId());
        request.withPipelineId(exec.getPiplineId());
        request.withPipelineRunId(exec.getPiplineRunId());
        try {
            ShowPipelineRunDetailResponse response = client.showPipelineRunDetail(request);
            log.info("{}",response);
            execWithRunDetailRespVO.setResponse(response);
        } catch (Exception e) {
            log.error(e.getMessage());
            return error(1,e.getMessage());
        }
        return success(execWithRunDetailRespVO);
    }

    @GetMapping("/page")
    @Operation(summary = "获得部署执行分页")
    //@PreAuthorize("@ss.hasPermission('pi:exec:query')")
    @PermitAll
    @TenantIgnore
    public CommonResult<PageResult<ExecRespVO>> getExecPage(@Valid ExecPageReqVO pageReqVO) {
        PageResult<ExecDO> pageResult = execService.getExecPage(pageReqVO);
        return success(BeanUtils.toBean(pageResult, ExecRespVO.class));
    }

}
